package org.example3_chatgpt;

import org.springframework.boot.loader.archive.JarFileArchive;
import org.springframework.boot.loader.archive.Archive;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * 借助Spring Boot的JarFileArchive类,我们可以读取外部JAR文件中的嵌套JAR文件.
 */
public class SpringNestedJarLoader {

    public static void main(String[] args) throws Exception {
        String jarPath = System.getProperty("user.dir") + "/jarFileRear/jarFileDir/nestedJar.jar";

        File outerJar = new File(jarPath);
        JarFileArchive archive = new JarFileArchive(outerJar);

        String innerJarPath = "org/example/simpleJarExample.jar"; // 内层 JAR 文件在外层 JAR 中的路径

        HashMap<String, Class> map = new HashMap<>();

        List<Archive> nestedArchives = archive.getNestedArchives(new Archive.EntryFilter() {
            @Override
            public boolean matches(Archive.Entry entry) {
                if (entry.getName().endsWith(".jar")) {
                    System.out.println("matches------" + entry.getName());
                    return true;
                }
                return false;
            }
        });

        System.out.println("nestedArchives:--------- " + nestedArchives.size());

        // 遍历并加载所有嵌套的 JAR 文件
        for (Archive archive1 : nestedArchives) {
            URL url = archive1.getUrl();
            System.out.println(url);

            URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});


            Iterator<Archive.Entry> iterator = archive1.iterator();

            while (iterator.hasNext()) {

                Archive.Entry entry = iterator.next();
                if (!entry.isDirectory() & entry.getName().endsWith(".class")) {
                    System.out.println(entry.getName());

                    Class<?> aClass = urlClassLoader.loadClass(entry.getName().replace(".class", "").replace("/", "."));
                    System.out.println("loaded class---------" +aClass.getName());
                    System.out.println(aClass.getClassLoader());

                    map.put(aClass.getName(), aClass);

                    Method main = aClass.getMethod("main", String[].class);
                    main.invoke(null, (Object) new String[0]);
                    System.out.println();
                }
            }
        }

        System.out.println("------------------------------------------------------------");
        Class aClass = map.get("org.example.HelloWorld");
        System.out.println(aClass.getClassLoader());
        Method main = aClass.getMethod("main", String[].class);
        main.invoke(null, (Object) new String[0]);

    }
}

